namespace C1.Win.C1FlexGrid.Util.BaseControls
{
    using System;
    using System.Globalization;
    using System.Windows.Forms;

    internal class InputMask
    {
        private bool _backSpace;
        private char _case;
        private Control _ctl;
        private int _first = -1;
        private string _mask;
        private string _maskString;
        private char _space = '_';
        private const string _specialChars = "09#L?Aa&";
        private bool _updating;
        private const char SC_ANY = '\b';
        private const char SC_CHARDEC = '\t';
        private const char SC_CHARDT = '\f';
        private const char SC_CHARTHOU = '\n';
        private const char SC_CHARTM = '\v';
        private const char SC_DGT = '\x0001';
        private const char SC_DGTSPC = '\x0002';
        private const char SC_DGTSPCSGN = '\x0003';
        private const char SC_LAST = '\r';
        private const char SC_LTR = '\x0004';
        private const char SC_LTRDGT = '\x0006';
        private const char SC_LTRDGTSPC = '\a';
        private const char SC_LTRSPC = '\x0005';

        internal InputMask(Control ctl)
        {
            this._ctl = ctl;
        }

        internal string ApplyMask()
        {
            string str = string.Empty;
            int num = 0;
            string content = this.GetContent();
            for (int i = 0; i < this._mask.Length; i++)
            {
                if (this._mask[i] > '\b')
                {
                    str = str + this._mask[i];
                    continue;
                }
                bool flag = false;
                while (num < content.Length)
                {
                    char c = content[num++];
                    flag = (c == this._space) || CharMatch(c, this._mask[i]);
                    if (flag)
                    {
                        if (this._case == '>')
                        {
                            c = char.ToUpper(c);
                        }
                        if (this._case == '<')
                        {
                            c = char.ToLower(c);
                        }
                        str = str + c;
                        break;
                    }
                }
                if (!flag)
                {
                    str = str + this._space;
                }
            }
            return str;
        }

        internal static bool CharMatch(char c, char mask)
        {
            switch (mask)
            {
                case '\x0001':
                    return char.IsDigit(c);

                case '\x0002':
                    if (!char.IsDigit(c))
                    {
                        return (c == ' ');
                    }
                    return true;

                case '\x0003':
                    return (char.IsDigit(c) || (((c == ' ') || (c == '+')) || (c == '-')));

                case '\x0004':
                    return char.IsLetter(c);

                case '\x0005':
                    if (!char.IsLetter(c))
                    {
                        return (c == ' ');
                    }
                    return true;

                case '\x0006':
                    return char.IsLetterOrDigit(c);

                case '\a':
                    if (!char.IsLetterOrDigit(c))
                    {
                        return (c == ' ');
                    }
                    return true;

                case '\b':
                    return true;
            }
            return (c == mask);
        }

        public int EditPosition(int index)
        {
            int num = (this._mask != null) ? this._mask.Length : 0;
            if (num == 0)
            {
                return index;
            }
            int num2 = 0;
            for (int i = 0; i < num; i++)
            {
                if (this._mask[i] <= '\b')
                {
                    if (num2 == index)
                    {
                        return i;
                    }
                    num2++;
                }
            }
            return num;
        }

        internal string GetContent()
        {
            string str = string.Empty;
            if ((this._mask == null) || (this._mask.Length == 0))
            {
                return this._ctl.Text;
            }
            string text = this._ctl.Text;
            int selectionStart = this.SelectionStart;
            int num2 = this._mask.Length - text.Length;
            for (int i = 0; i < text.Length; i++)
            {
                int num4 = i;
                if (i >= selectionStart)
                {
                    num4 += num2;
                }
                if (((num4 < 0) || (num4 >= this._mask.Length)) || ((this._mask[num4] <= '\b') || !CharMatch(text[i], this._mask[num4])))
                {
                    str = str + text[i];
                }
            }
            return str;
        }

        internal string GetValidContent()
        {
            string text = this._ctl.Text;
            string str2 = string.Empty;
            if ((this._mask == null) || (this._mask.Length == 0))
            {
                return text;
            }
            int num = 0;
            for (int i = 0; i < this._mask.Length; i++)
            {
                char ch2;
                char mask = this._mask[i];
                if (num < text.Length)
                {
                    ch2 = text[num];
                    if (ch2 != this._space)
                    {
                        goto Label_00A1;
                    }
                    switch (mask)
                    {
                        case '\x0002':
                        case '\x0003':
                        case '\x0005':
                        case '\a':
                        case '\b':
                            str2 = str2 + ' ';
                            goto Label_009B;
                    }
                }
                return null;
            Label_009B:
                num++;
                continue;
            Label_00A1:
                if (!CharMatch(ch2, mask))
                {
                    return null;
                }
                str2 = str2 + ch2;
                num++;
            }
            if (num != text.Length)
            {
                return null;
            }
            return str2;
        }

        internal bool IsUpdating()
        {
            return this._updating;
        }

        internal bool OnKeyPress(KeyPressEventArgs e)
        {
            if ((this._mask == null) || (this._mask.Length == 0))
            {
                return true;
            }
            this._backSpace = e.KeyChar == '\b';
            if (char.IsControl(e.KeyChar))
            {
                return true;
            }
            int selectionStart = this.SelectionStart;
            if (selectionStart < this._first)
            {
                selectionStart = this.SelectionStart = this._first;
            }
            if (((selectionStart > -1) && (selectionStart < this._mask.Length)) && !CharMatch(e.KeyChar, this._mask[selectionStart]))
            {
                e.Handled = true;
            }
            if (selectionStart == this._mask.Length)
            {
                e.Handled = true;
            }
            return !e.Handled;
        }

        internal bool OnTextChanged(EventArgs e)
        {
            if (this._updating)
            {
                return false;
            }
            if ((this._mask != null) && (this._mask.Length != 0))
            {
                string str = this.ApplyMask();
                if (str == this._ctl.Text)
                {
                    return false;
                }
                int selectionStart = this.SelectionStart;
                this._updating = true;
                this._ctl.Text = str;
                if (selectionStart > -1)
                {
                    if (selectionStart == 0)
                    {
                        this._backSpace = false;
                    }
                    while (((selectionStart < (this._mask.Length - 1)) && (this._mask[selectionStart] >= '\t')) && !this._backSpace)
                    {
                        selectionStart++;
                    }
                    if (selectionStart < this._first)
                    {
                        selectionStart = this._first;
                    }
                    this.Select(selectionStart, 0);
                }
                this._updating = false;
            }
            return true;
        }

        internal void Select(int start, int length)
        {
            if (!(this._ctl is TextBox))
            {
                throw new Exception("Shouldn't happen!");
            }
            ((TextBox) this._ctl).Select(start, length);
        }

        public string Mask
        {
            get
            {
                return this._maskString;
            }
            set
            {
                this._maskString = value;
                this._first = -1;
                this._case = '\0';
                this._space = '_';
                this._mask = null;
                if ((this._maskString != null) && (this._maskString.Length != 0))
                {
                    NumberFormatInfo currentInfo = NumberFormatInfo.CurrentInfo;
                    DateTimeFormatInfo info2 = DateTimeFormatInfo.CurrentInfo;
                    this._mask = string.Empty;
                    for (int i = 0; i < this._maskString.Length; i++)
                    {
                        char ch = this._maskString[i];
                        if (ch == 'C')
                        {
                            ch = '&';
                        }
                        int index = "09#L?Aa&".IndexOf(ch);
                        if (index > -1)
                        {
                            if (this._first < 0)
                            {
                                this._first = this._mask.Length;
                            }
                            this._mask = this._mask + ((char) (index + 1));
                        }
                        else
                        {
                            switch (ch)
                            {
                                case ',':
                                    this._mask = this._mask + currentInfo.CurrencyGroupSeparator;
                                    goto Label_021D;

                                case '.':
                                    this._mask = this._mask + currentInfo.CurrencyDecimalSeparator;
                                    goto Label_021D;

                                case '/':
                                    this._mask = this._mask + info2.DateSeparator;
                                    goto Label_021D;

                                case ':':
                                    this._mask = this._mask + info2.TimeSeparator;
                                    goto Label_021D;

                                case ';':
                                    if ((this._maskString.Length <= (i + 1)) || (this._maskString[i + 1] < ' '))
                                    {
                                        break;
                                    }
                                    this.PlaceHolder = this._maskString[i + 1];
                                    i = this._maskString.Length;
                                    goto Label_021D;

                                case '<':
                                    this._case = ch;
                                    goto Label_021D;

                                case '>':
                                    this._case = ch;
                                    goto Label_021D;

                                case '\\':
                                    if (i < (this._maskString.Length - 1))
                                    {
                                        i++;
                                    }
                                    this._mask = this._mask + this._maskString[i];
                                    goto Label_021D;
                            }
                            this._mask = this._mask + ch;
                        Label_021D:;
                        }
                    }
                }
            }
        }

        public char PlaceHolder
        {
            get
            {
                return this._space;
            }
            set
            {
                if (value < ' ')
                {
                    throw new ArgumentException("PlaceHolder must be a printable character.");
                }
                this._space = value;
            }
        }

        internal int SelectionStart
        {
            get
            {
                if (this._ctl is TextBox)
                {
                    return ((TextBox) this._ctl).SelectionStart;
                }
                return -1;
            }
            set
            {
                if (this._ctl is TextBox)
                {
                    ((TextBox) this._ctl).SelectionStart = value;
                }
            }
        }
    }
}

